package com.bee.member.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.bee.base.BaseApiService;
import com.bee.base.BaseResponse;
import com.bee.constants.Constants;
import com.bee.core.token.GenerateToken;
import com.bee.core.transaction.RedisDataSoureceTransaction;
import com.bee.core.utils.MD5Util;
import com.bee.member.input.dto.UserLoginInpDTO;
import com.bee.member.mapper.UserMapper;
import com.bee.member.mapper.UserTokenMapper;
import com.bee.member.mapper.entity.UserDo;
import com.bee.member.mapper.entity.UserTokenDo;
import com.bee.member.service.MemberLoginService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.TransactionStatus;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MemberLoginServiceImpl extends BaseApiService<JSONObject> implements MemberLoginService {

    @Autowired
    private UserTokenMapper userTokenMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private GenerateToken generateToken;

    /**
     * 手动事务工具类
     */
    @Autowired
    private RedisDataSoureceTransaction manualTransaction;


    @Override
    public BaseResponse<JSONObject> login(@RequestBody UserLoginInpDTO userLoginInpDTO) {
        // 1.验证参数
        String mobile = userLoginInpDTO.getMobile();
        if (StringUtils.isEmpty(mobile)) {
            return setResultError("手机号码不能为空!");
        }
        String password = userLoginInpDTO.getPassword();
        if (StringUtils.isEmpty(password)) {
            return setResultError("密码不能为空!");
        }
        String loginType = userLoginInpDTO.getLoginType();
        if (StringUtils.isEmpty(loginType)) {
            return setResultError("登陆类型不能为空!");
        }
        if (!(loginType.equals(Constants.MEMBER_LOGIN_TYPE_ANDROID) || loginType.equals(Constants.MEMBER_LOGIN_TYPE_IOS)
                || loginType.equals(Constants.MEMBER_LOGIN_TYPE_PC))) {
            return setResultError("登陆类型出现错误!");
        }

        // 设备信息
        String deviceInfor = userLoginInpDTO.getDeviceInfor();
        if (StringUtils.isEmpty(deviceInfor)) {
            return setResultError("设备信息不能为空!");
        }
        //2.密码加密
        String ecdpassword = MD5Util.MD5(password);
        //3.验证登录信息
        UserDo userDo = userMapper.login(mobile, ecdpassword);
        if(userDo == null){
            return setResultError("用户名或者密码不正确");
        }
        TransactionStatus transactionStatus = null;
        try {

            //4.验证用户是否已经登录
            Long uid = userDo.getUserId();
            UserTokenDo userTokenDo = userTokenMapper.selectByUserIdAndLoginType(uid, loginType);

            transactionStatus = manualTransaction.begin();
            // // ####开启手动事务

            if (userTokenDo != null) {
                String token = userTokenDo.getToken();
                generateToken.removeToken(token);
                int updateTokenAvailability = userTokenMapper.updateTokenAvailability(token);
                if (updateTokenAvailability < 0) {
                    manualTransaction.rollback(transactionStatus);
                    return setResultError("系统错误");
                }
                //问题：如何保证redis和db的一致性问题  手动事务
            }
            // 如果有传递openid参数，修改到数据中
            String qqOpenId = userLoginInpDTO.getQqOpenId();
            if (!StringUtils.isEmpty(qqOpenId)) {
                userMapper.updateUserOpenId(qqOpenId, uid);
            }

            String keyPrifix = Constants.MEMBER_TOKEN_KEYPREFIX + loginType;
            String newToken = generateToken.createToken(keyPrifix, uid + "");

            // 1.插入新的token
            UserTokenDo userToken = new UserTokenDo();
            userToken.setUserId(uid);
            userToken.setLoginType(loginType);
            userToken.setToken(newToken);
            userToken.setDeviceInfor(deviceInfor);
            int result = userTokenMapper.insertUserToken(userToken);
            if (!toDaoResult(result)) {
                manualTransaction.rollback(transactionStatus);
                return setResultError("系统错误!");
            }
            //提交事务
            JSONObject data = new JSONObject();
            data.put("token", newToken);
            manualTransaction.commit(transactionStatus);
            return setResultSuccess(data);
        }catch (Exception e) {
            try {
                // 回滚事务
                manualTransaction.rollback(transactionStatus);
            } catch (Exception e1) {
            }
            return setResultError("系统错误!");
        }
    }
}
